package com.youhui.weixin.service.task;

import com.youhui.weixin.common.MythConfig;
import com.youhui.weixin.common.exception.MythException;
import com.youhui.weixin.common.info.MythExceptionList;
import com.youhui.weixin.dao.GoodsDao;
import com.youhui.weixin.dao.GoodsLinkDao;
import com.youhui.weixin.domain.Goods;
import com.youhui.weixin.domain.GoodsLink;
import com.youhui.weixin.service.ExcelRedisService;
import com.youhui.weixin.utils.excel.DealType;
import com.youhui.weixin.utils.excel.ExcelData;
import com.youhui.weixin.utils.excel.Position;
import com.youhui.weixin.utils.excel.ReflectUtils;
import com.youhui.weixin.websocket.WebSocketClient;
import lombok.extern.log4j.Log4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.youhui.weixin.common.MythConfig.EXCEL_READ_DEFINE;
import static com.youhui.weixin.common.MythConfig.USER_ID;

/**
 * Created by https://github.com/kuangcp on 17-10-21  下午4:22
 * 异步保存
 * @author kuangcp
 */
@Service
@Log4j
public class SaveExcelDataTask {
    @Autowired
    GoodsDao goodsDao;
    @Autowired
    GoodsLinkDao goodsLinkDao;
    @Autowired
    DealType dealType;
//    private static Gson gson = new Gson();

    // 处理异常
//    @Async
//    public Future<String> saveDataToDB(ExcelData data, int start, int end, Set<String> result, HashOperations<String, String, String> hash) {
//        Map<String, Object> map = new HashMap<>();
//
//        Object temp;
//        Future<String> future = null;
//        // TODO 这个map转出成对象耗时高
//        for (int row = start; row <= end; row++) {
//            for (String key : result) {
////                log.info(key);
//                temp = data.getContents().get(Position.init(row, readColNum(hash.get(MythConfig.EXCEL_READ_DEFINE, key))));
//                if (temp == null || "".equals(temp) || " ".equals(temp) || "无".equals(temp)) {
//                    map.put(key, null);
//                } else {
//                    try {
//                        readData(map, key, temp);
//                    } catch (MythException e) {
//                        future = new AsyncResult<>(e.getMessage());
//                        log.info("有异常"+e.getMessage());
//                        e.printStackTrace();
//                        return future;
//                    }finally {
//                        dealType.flushMapCache();
//                    }
//                }
//            }
//            // 过滤掉没有优惠券的商品
//            if (map.get("link") == null) {
//                // 不做处理
//                map.clear();
//            } else {
//                Goods goods;
//                // 保存到redis中去
//                try {
//                    goods = (Goods) ReflectUtils.mapToEntity(map, Goods.class.getName());
//                    goods.setImportTime(new Date());
//                    goods.setTypeId(dealType.handle(goods.getName()));//处理分类
////                    hash.put(MythConfig.GOODS_KEY, goods.getGoodsId().toString(), gson.toJson(goods));
//                    log.info(goods.toString());
//                    goodsDao.save(goods);
//                } catch (UnsupportedEncodingException | MythException e) {
//                    future = new AsyncResult<>(e.getMessage());
//                    log.info("有异常"+e.getMessage());
//                    e.printStackTrace();
//                    return future;
//                }finally {
//                    dealType.flushMapCache();
//                }
//            }
//        }
//
//        dealType.flushMapCache();
//        return future;
//    }

    @Async
    public void saveDataToDB(ExcelData data, int start, int end, Set<String> result,
                             HashOperations<String, String, String> hash, String adminId) {
        Map<String, Object> map = new HashMap<>();
        Date now = new Date();
        Object temp;
        for (int row = start; row <= end; row++) {
            for (String key : result) {
                temp = data.getContents().get(Position.init(row, readColNum(hash.get(EXCEL_READ_DEFINE, key))));
                if (temp == null || "".equals(temp) || " ".equals(temp) || "无".equals(temp)) {
                    map.put(key, null);
                } else {
                    try {
                        readData(map, key, temp);
                    } catch (Exception e) {
                        log.info("有异常"+e.getClass().getName()+e.getMessage());
                        sendError(adminId);
//                        e.printStackTrace();
                        return;
                    }
                }
            }
            // 过滤掉没有优惠券的商品 或者不是拥有者的分享链接
//            if (map.get("link") == null){
            if (map.get("link") == null || !map.get("link").toString().contains(USER_ID)) {
                // 不做处理
                map.clear();
            } else {
                Goods goods;
                // 保存到redis中去
                try {
                    goods = (Goods) ReflectUtils.mapToEntity(map, Goods.class.getName());
                    goods.setImportTime(now);
                    //无条件的就直接减，否则就是原价
                    if(goods.getDiscountDetail().contains("无条件")){
                        goods.setPriceDiscount(goods.getPrice()-goods.getDiscount());
                    }else{
                        goods.setPriceDiscount(goods.getPrice());
                    }
                    goods.setTypeId(dealType.handle(goods.getName()));//处理分类
                    goods.setLink(dealType.handleLink(goods.getGoodsId(), goods.getLink())); //处理长链接

//                    log.info(dealType.handle(goods.getName())+" || "+goods.getName());
//                    hash.put(MythConfig.GOODS_KEY, goods.getGoodsId().toString(), gson.toJson(goods));
//                    log.info(goods.toString());
                    log.info("保存："+goods.getGoodsId()+goods.getName()+"|"+goods.getTypeId()+"|"+goods.getAlreadyBuy());

                    goodsDao.save(goods);
//                    goodsLinkDao.save(new GoodsLink(goods.getGoodsId(), goods.getLink()));
                } catch (UnsupportedEncodingException | MythException e) {
                    log.info("有异常"+e.getMessage());
                    sendError(adminId);
                    e.printStackTrace();
                    return;
                }
            }
        }

    }

    private void sendError(String id){
        WebSocketClient client;
        try {
            client = WebSocketClient.connect(MythConfig.SYSTEM_SOCKET);
            // 发送消息， id 为接受者id, text为发送的信息
            client.sendMessage(id, System.currentTimeMillis()+" 文件导入有错误，请重新配置后导入");
            // 关闭连接
            client.onClosing();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    /**
     * 将配置文件中数据进行转换
     * @param col 配置数据 字母
     * @return 实际列数
     */
    private int readColNum(String col) {
        col = col.trim();
        if(col.length() == 1){
            return col.toCharArray()[0] - 'A' + 1;
        }else if (col.length() == 2){
            return (col.toCharArray()[0] - 'A' + 1) * 26 + (col.toCharArray()[1] - 'A' + 1);
        }
        return 0;
    }
    /**
     * 将配置文件中定义的列，全部自行转换 得到正确类型 放入map
     * @param map 缓存映射
     * @param key 键
     * @param object 值
     */
    private void readData(Map<String, Object> map, String key, Object object) throws Exception {
//        log.info(key+"|||||"+object.toString());
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        if("goodsId".equals(key)){
            map.put(key, Long.valueOf(object.toString()));
        }else if("discount".equals(key)) {
            map.put("discountDetail",object.toString());
            String[] names = object.toString().split("减");
            String discount;
            if (names.length > 1) {
                discount = names[1].split("元")[0];
            }else{
                names = object.toString().split("元");
                discount = names[0];
            }
            map.put(key, Integer.parseInt(discount));
        }else if("alreadyBuy".equals(key)){
            map.put(key, Integer.valueOf(object.toString()));
        }else if("price".equals(key)){
            map.put(key, Float.valueOf(object.toString()));
        }else if("startTime".equals(key) || "endTime".equals(key)){
            try {
                map.put(key, simpleDateFormat.parse(object.toString()));
            } catch (ParseException e) {
                throw new MythException(MythExceptionList.PARSE_TYPE_EXCEPTION, e, ExcelRedisService.class);
            }
        }else{
            map.put(key, object.toString());
        }
    }
}
